﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using FinalTestMachine.Motion.Product;

namespace FinalTestMachine.MES
{
    public class MESHelper
    {
        public static readonly MESHelper Cur = new MESHelper();

        private MESHelper()
        {
            MESCommand.End = "#end";
            MESCommand.GetStationNameEventHandler += () => Motion.OtherParamHelper.Cur.MESStationName.GetValue;
            CommandLogin = new MESCommand("登录", "ff0x01", "LoginUp");
            CommandCheckSN = new MESCommand("CheckSn", "ff0x02", "CheckSn");
            CommandDataUpLoad = new MESCommand("数据上传", "ff0x04", "DataUp");
            MesConnect.RecevieMsgActionEventHander += Cur_getMasterMsgEventHandle;
        }

        public static MESHelper CreateInstance()
        {
            return Cur;
        }

        public IConnectDLL.IConnect MesConnect => Connect.ConnectFactory.tcpClientMes;

        private MESCommand CommandLogin;    //登录
        private MESCommand CommandCheckSN; //Check SN
        private MESCommand CommandDataUpLoad; //上传数据

        private object _lockSend = new object();
        private ILog_dll.LogProcessHelper _mesLogger = new ILog_dll.LogProcessHelper("MES运控日志");

        public Action<string> WriteToUserEventHandler;

        public void WriteToUser(string msg) => _mesLogger.Write(msg);

        private bool MESResponse(MESCommand command, out string returnMessage)
        {
            lock (_lockSend)
            {
                try
                {
                    if (MesConnect.IsConnected == false)
                    {
                        returnMessage = "MES通讯未连接，请检查通讯状态";
                        return false;
                    }
                    returnMessage = "";
                    string content = command.ToString();
                    WriteToUser("准备向MES发送信息:" + content);
                    if (MESCommand.MESCommandDict.ContainsKey(command.Header))
                    {
                        MESCommand.MESCommandDict[command.Header].Result = new MESResult();
                    }
                    MesConnect.Send(command.ToString());
                    WriteToUser("向MES发送信息完成:" + content);
                    System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
                    timer.Restart();
                    while (true)
                    {
                        if (MESCommand.MESCommandDict[command.Header].Result.Result == true)
                        {
                            return true;
                        }
                        else if (MESCommand.MESCommandDict[command.Header].Result.Result == false)
                        {
                            returnMessage = MESCommand.MESCommandDict[command.Header].Result.Msg;
                            return false;
                        }
                        else if (timer.ElapsedMilliseconds > 10000)
                        {
                            returnMessage = "MES回复超时";
                            return false;
                        }
                    }
                }
                catch (Exception ex)
                {
                    returnMessage = "向MES发送消息时异常:" + AM.Tools.ExceptionHelper.GetInnerExceptionMessageAndStackTrace(ex);
                    return false;
                }
            }
        }

        public void GetMesResult(string message)
        {
            MESResult result = new MESResult();
            string error = String.Empty;
            string header = String.Empty;
            try
            {
                string[] strArray = message.Split(';');
                header = strArray[0];
                result.Header = header;

                if (MESCommand.MESCommandDict.ContainsKey(strArray[0]) == false)
                {
                    error = "MES解析发现未注册该命令头:" + strArray[0] + "," + message;
                    WriteToUser(error);
                    throw new Exception(error);
                }
                else if (strArray.Length < 2)
                {
                    error = "收到MES消息解析后格式长度不正确：" + message;
                    WriteToUser(error);
                    result.Msg = error;
                    result.Result = false;
                }
                else
                {
                    string data = strArray[2];
                    string[] dataArray = strArray[2].Split(new string[] { "Data:" }, options: StringSplitOptions.None)[1].Split(new char[] { ',' }, options: StringSplitOptions.RemoveEmptyEntries);
                    string other = string.Empty;
                    foreach (var item in dataArray)
                    {
                        //if (item.Contains("Result="))
                        //{
                        //    result.Result = item.Split('=')[1].ToUpper() == "OK" ? true : false;
                        //}
                        if (item.Contains("Result"))
                        {
                            var items = item.Split(new string[] { "Result" }, StringSplitOptions.None);
                            result.Result = item.Split(new string[] { "Result" }, StringSplitOptions.None)[1].Trim().ToUpper().Contains("OK") ? true : false;
                        }
                        else if (item.Contains("Msg="))
                        {
                            result.Msg = item.Split('=')[1];
                        }
                        else
                        {
                            other += item + ",";
                        }
                    }
                }

                MESCommand.MESCommandDict[header].Result = result;
            }
            catch (Exception ex)
            {
                WriteToUser($"运控解析MES信息:{message}出现异常:" + AM.Tools.ExceptionHelper.GetInnerExceptionMessageAndStackTrace(ex));
                throw;
            }
            finally
            {
            }
        }

        private void Cur_getMasterMsgEventHandle(string obj)
        {
            this.WriteToUser("收到MES消息:" + obj);
            string cmd = obj.Split(';')[0];
            this.WriteToUser("收到MES消息解析命令头为:" + cmd);

            try
            {
                if (MESCommand.MESCommandDict.ContainsKey(cmd))
                {
                    GetMesResult(obj);
                    return;
                }
                switch (cmd)
                {
                    case "ff0x05":    //换型
                        if (Motion.StaticInitial.Motion.CurOrder.IsAutoRunning == false)
                        {
                            this.WriteToUser("响应MES换型命令");
                            try
                            {
                                var modelName = obj.Split(new string[] { "Model=" }, StringSplitOptions.None)[1].Split(';')[0];
                                var modeArray = View.WorkItemManagerHelper.workIterm.ItermMessagesCollection;
                                for (int i = 0; i < modeArray.Count; i++)
                                {
                                    if (modeArray[i].Name == modelName)
                                    {
                                        View.WorkItemManagerHelper.workIterm.ModifyCurrentPath(modeArray[i]);
                                        return;
                                    }
                                }

                                Motion.StaticInitial.Motion.WriteErrToUser("MES换型失败，未找到对应型号:" + modelName + "," +
                                    "MES原始命令:" + obj);
                                MesConnect.Send($"ff0x05;Command:Remodel;Data:Model={View.WorkItemManagerHelper.LoadedName};#end");
                            }
                            catch (Exception ex)
                            {
                                Motion.StaticInitial.Motion.WriteErrToUser("MES换型时发生异常：" + ex.Message);
                            }
                        }
                        else
                        {
                            Motion.StaticInitial.Motion.WriteErrToUser("当前处于自动流程，无法响应MES换型命令");
                        }

                        break;

                    case "ff0x06":    //清料
                        this.WriteToUser("响应MES清料命令");
                        MesConnect.Send($"ff0x06;Command:Clean;#end");

                        break;

                    case "ff0x07":    //开始
                        if (Motion.StaticInitial.Motion.CurOrder.IsAutoRunning == false)
                        {
                            this.WriteToUser("响应MES开始命令");
                            Motion.StaticInitial.Motion.CommitStartRunOrder();
                        }
                        MesConnect.Send($"ff0x07;Command:Start;#end");

                        break;

                    case "ff0x08":    //停止
                        if (Motion.StaticInitial.Motion.CurOrder.IsAutoRunning == true)
                        {
                            this.WriteToUser("响应MES停止命令");
                            Motion.StaticInitial.Motion.CommitStopOrder();
                        }
                        MesConnect.Send($"ff0x08;Command:Stop;#end");

                        break;

                    case "ff0x09":    //复位
                        if (Motion.StaticInitial.Motion.CurOrder.IsAutoRunning == false)
                        {
                            this.WriteToUser("响应MES复位命令");
                            Motion.StaticInitial.Motion.CommitResOrder();
                        }
                        else
                        {
                            Motion.StaticInitial.Motion.WriteErrToUser("MES复位失败，当前处于自动流程，无法执行MES复位命令");
                        }
                        MesConnect.Send($"ff0x09;Command:Reset;#end");

                        break;

                    default:
                        break;
                }
            }
            catch (Exception ex)
            {
                Motion.StaticInitial.Motion.WriteErrToUser("收到MES消息处理MES命令时发生异常:" + AM.Tools.ExceptionHelper.GetInnerExceptionMessageAndStackTrace(ex));
                WriteToUser("收到MES消息处理MES命令时发生异常:" + AM.Tools.ExceptionHelper.GetInnerExceptionMessageAndStackTrace(ex));
            }
        }

        public bool? CheckLogin(string userName, string password, out string error)
        {
            error = string.Empty;
            try
            {
                StringBuilder sb = new StringBuilder(128);
                sb.Append("Data:");
                sb.Append($"user={userName},password={password}");
                CommandLogin.SetData(sb.ToString());
                return MESResponse(CommandLogin, out error);
            }
            catch (Exception ex)
            {
                this.WriteToUser("CheckLogin函数异常" + ex.Message + ex.StackTrace);
                return false;
            }
        }

        public bool? CheckSN(string sn, out string error)
        {
            error = string.Empty;
            try
            {
                StringBuilder sb = new StringBuilder(128);
                sb.Append("Data:");
                sb.Append($"Sn={sn},Model={View.WorkItemManagerHelper.LoadedName}");
                CommandCheckSN.SetData(sb.ToString());
                return MESResponse(CommandCheckSN, out error);
            }
            catch (Exception ex)
            {
                error = "运控软件执行异常，" + ex.Message;
                this.WriteToUser("CheckSN函数异常" + AM.Tools.ExceptionHelper.GetInnerExceptionMessageAndStackTrace(ex));
                return false;
            }
        }

        public bool? DataUp(ProductInfo product, out string error)
        {
            error = string.Empty;
            try
            {
                var startTime = GetTimeStamp(product.StartTime);
                var endTime = GetTimeStamp(product.EndTime);
                StringBuilder sb = new StringBuilder(128);
                sb.Append("Data:");
                sb.Append($"Sn={product.Number},TestResult={(product.Result == ProductInfo.ResultOK ? "OK" : "NG")},Model={View.WorkItemManagerHelper.LoadedName},");
                sb.Append($"StartTime={startTime},EndTime={endTime},");
                var testItmes = this.GetTestValueItems(product);
                sb.Append($"TestValue={testItmes}");

                CommandDataUpLoad.SetData(sb.ToString());
                return MESResponse(CommandDataUpLoad, out error);
            }
            catch (Exception ex)
            {
                error = "运控软件执行异常，" + ex.Message;
                this.WriteToUser("DataUp函数异常:" + AM.Tools.ExceptionHelper.GetInnerExceptionMessageAndStackTrace(ex));
                return false;
            }
        }

        public string GetTestValueItems(ProductInfo product)
        {
            StringBuilder sb = new StringBuilder(1024);
            StringBuilder testImagePath = new StringBuilder();
            StringBuilder resultImagePath = new StringBuilder();
            foreach (var item in product.GetAllTestItems())
            {
                if (item.name.ToLower().Equals("testimage"))
                {
                    testImagePath.Append(item.value + "|");
                    break;
                }

                if (item.name.ToLower().Equals("resultimage"))
                {
                    resultImagePath.Append(item.value + "|"); 
                    break;
                }

                string resultStr = String.Empty;
                if (item.result == Motion.Product.ProductInfo.ResultNG
                      || item.result == "0" || item.result.ToLower() == "ng"
                          || item.result.ToLower() == "fail")
                {
                    resultStr = "NG";
                }
                else
                {
                    resultStr = "OK";
                }
                sb.Append($"{item.name}@{item.lowLimit}@{item.upLimit}@{item.value}@{resultStr}|");
            }
            if (product.GetAllTestItems().Count != 0)
            {
                sb = sb.Remove(sb.Length - 1, 1);
            }
            sb.Append(";");
            sb.Append($"TestImage={(testImagePath.Length >= 1 ? testImagePath.Remove(testImagePath.Length - 1,1) : null)};");
            sb.Append($"ResultImage={(resultImagePath.Length >= 1 ? resultImagePath.Remove(resultImagePath.Length - 1,1) : null)};");
            sb.Append($"Enabled=1");

            return sb.ToString();
        }

        public string GetTimeStamp(string date)
        {
            DateTime dt = Convert.ToDateTime(date);
            DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1, 0, 0, 0, 0));
            long timeStamp = (long)(dt - startTime).TotalMilliseconds;
            return timeStamp.ToString();
        }
    }
}